昨天量到 ping 的顯示下限是 1 微秒。今天使用有硬體時戳的ExaNIC X25的兩個 port 用一條 3 公尺 DAC 直接對接。同一個封包用兩種時戳各量一次,看差多少。
(已將敏感資訊遮蔽,例如:MAC、IP、Hostname等)
先看卡認不認得到,還有兩個 port 的 link。
exanic-config

再確認這兩個 port 是不是同一張卡。
for n in ens8191 ens8191d1; do printf '%-12s numa_node=%-4s ' "$n" "$(cat /sys/class/net/$n/device/numa_node 2>/dev/null)"; ethtool -i "$n" 2>/dev/null | sed -n 's/^\(driver\|firmware-version\|bus-info\):/\1:/p' | tr '\n' ' '; echo; done

兩個介面同一個 bus-info。 Day 1 說"同一張卡的兩個 port 共用同一顆時鐘、時戳可以直接相減" 這行就是那句話的證據。不是同一顆時鐘的話,兩端相減會混進時鐘偏移。
然後發一萬個封包,把每個封包的硬體時戳差跟軟體時戳差都倒出來。
python3 ~/lab/stats.py ~/lab/f4_3m.csv

同一個封包、同一瞬間,硬體說 60 奈秒,軟體說 1383 奈秒,差 23 倍。
但真正有意思的不是中位數,是這一萬筆各自出現過幾種值。

一萬個封包,硬體時戳只給出五種答案,而且每兩種之間剛好差 4 奈秒。
那 4 奈秒就是卡上那顆計數器走一格的時間。硬體時戳不是「量得比較準」,是它在一條刻度尺上讀數,而那把尺的最小刻度是 4 奈秒。比 4 奈秒細的東西它也看不到,只是對我要量的幾百奈秒來說,這個刻度夠細了。
軟體那欄 268 種值、範圍橫跨 5479 奈秒。那個離散度不是網路造成的,這一萬個封包走的是同一條 3 公尺銅線,物理上不可能一下 1299 一下 6778。那是 CPU 在忙,是主機在排隊,跟線上發生的事無關。
今天六個步驟一次過,但有兩件事讓我愣了一下。
第一件,exanic0 不是網路介面。
ip link show exanic0 ---> 錯誤
ip link show ens8191 | head -1 ---> 正確

-1:指定只要開頭的 1 行。
exanic0 是 ExaNIC 工具自己的裝置名,Linux 這邊看到的是 ens8191 跟 ens8191d1。兩套命名各管各的:exanic-config 兩種都吃,ip 跟 ethtool 只吃介面名。
看起來是小事,但第一次碰的時候有讓我卡一下,因為錯誤訊息說的是「裝置不存在」,而我明明看著它在那裡。
第二件,tcpdump 什麼都抓不到。
timeout 5 tcpdump -i ens8191 -c 5 2>&1 | tail -5

結果顯示5秒一行都沒印出來。原因是量測前要把 port 設成 bypass-only,那個動作把 port 從 Linux 網路堆疊拿走,交給使用者空間的函式庫獨佔。封包確實在跑,只是 kernel 再也看不到它們,tcpdump 是跟 kernel 要資料的。
這件事後面談 kernel bypass 的時候會整段展開,今天先記著:
你把網卡交出去換速度,換掉的東西包括所有靠 kernel 運作的工具。
它的用途是先驗儀器,不是拿來跟網路比。
這 60 奈秒裡沒有任何網路,它是網卡自己收發一個封包的時間。所以每次要量之前先跑一次直連,中位數不是 60.0 就代表儀器或線材變了,這時候量出來的數字全部不能用。這條我拿同一條線重量了好幾次,每次五千個封包中位數每次都是 60.0。
手上沒有硬體時戳的話,不要量絕對值,量相對變化。
軟體時戳在同一批封包上給出 268 種值,那個離散度主要來自主機忙不忙。所以用軟體工具的時候只跟自己比,拿同一支工具在同一台機器上重跑,看今天跟上週差多少。真要留在軟體世界量延遲,業界用的是 sockperf 或 netperf 的 TCP_RR,不會有人用 ping。那兩支我還沒跑過,這裡只是點名。
要把這件事變成每天自動跑的巡檢,存下面三個數字就夠了。
| 存什麼 | 它會告訴你什麼 |
|---|---|
| 中位數 | 平常多快 |
| p99 減中位數 | 最壞的情況比平常糟多少 |
| 相異值個數 | 抖動變大了沒有 |
第三個是今天才想到的。硬體時戳只會落在 4 奈秒的格子上,這條直連線佔了五格。哪天同一條線變成八格十格,就是抖動變大了,而且這個訊號跟中位數有沒有移動無關——中位數可以一動也不動,格數卻悄悄變多。
明天把封包抓下來,看時戳是打在封包的哪個位置。